#include "irq.h"
#include "system.h"
#include "idt.h"

void *irq_routines[16] =
{
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0
};

void irq_install_handler(int irq, void (*handler)(struct regs *r)){
	irq_routines[irq] = handler;
}

void irq_uninstall_handler(int irq){
	irq_routines[irq] = 0;
}

void irq_remap(void){
	outportb(0x20, 0x11);
	outportb(0xA0, 0x11);
	outportb(0x21, 0x20);
	outportb(0xA1, 0x28);
	outportb(0x21, 0x04);
	outportb(0xA1, 0x02);
	outportb(0x21, 0x01);
	outportb(0xA1, 0x01);
	outportb(0x21, 0x0);
	outportb(0xA1, 0x0);
}

void irq_install(){
	irq_remap();
	install_isr(32, (unsigned)irq0, 0x08, 0x8E);
	install_isr(33, (unsigned)irq1, 0x08, 0x8E);
	install_isr(34, (unsigned)irq2, 0x08, 0x8E);
	install_isr(35, (unsigned)irq3, 0x08, 0x8E);
	install_isr(36, (unsigned)irq4, 0x08, 0x8E);
	install_isr(37, (unsigned)irq5, 0x08, 0x8E);
	install_isr(38, (unsigned)irq6, 0x08, 0x8E);
	install_isr(39, (unsigned)irq7, 0x08, 0x8E);
	install_isr(40, (unsigned)irq8, 0x08, 0x8E);
	install_isr(41, (unsigned)irq9, 0x08, 0x8E);
	install_isr(42, (unsigned)irq10, 0x08, 0x8E);
	install_isr(43, (unsigned)irq11, 0x08, 0x8E);
	install_isr(44, (unsigned)irq12, 0x08, 0x8E);
	install_isr(45, (unsigned)irq13, 0x08, 0x8E);
	install_isr(46, (unsigned)irq14, 0x08, 0x8E);
	install_isr(47, (unsigned)irq15, 0x08, 0x8E);
}


void irq_handler(struct regs *r){
	/* This is a blank function pointer */
	void (*handler)(struct regs *r);

	/* Find out if we have a custom handler to run for this
	 *     *  IRQ, and then finally, run it */
	handler = irq_routines[r->int_no];
	if (handler){
		handler(r);
	}

	/* If the IDT entry that was invoked was greater than 40
	 *     *  (meaning IRQ8 - 15), then we need to send an EOI to
	 *         *  the slave controller */
	if (r->int_no >= 40){
		outportb(0xA0, 0x20);
	}

	/* In either case, we need to send an EOI to the master
	 *     *  interrupt controller too */
	outportb(0x20, 0x20);
}

